package d1_stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

public class StreamTest03 {
    public static void main(String[] args) {
        //目标: 掌握Stream流的常见方法
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "陈平安", "宁姚", "陈十三", "陈凡", "姬紫月");
        //调用这个方法,每次会返回一个新的Stream流
        //Stream<T> filter(Predicate<? super T> predicate) 用于对流中数据的过滤
        //可以调用forEach()进行遍历
        /*list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return false;//写过滤条件
            }
        });*/
        //直接打印是一个流的地址值
        //java.util.stream.ReferencePipeline$2@3b07d329
        //System.out.println(list.stream().filter(s -> s.startsWith("陈")).filter(s -> s.length() == 3));
        //1、过滤方法
        list.stream().filter(s -> s.startsWith("陈")).filter(s -> s.length() == 3).forEach(System.out::println);

        //2、准备一个集合, 排序
        List<Movie> movies = new ArrayList<>();
        movies.add(new Movie("剑来", 9.9, "陈平安,宁姚"));
        movies.add(new Movie("遮天", 9.2, "姬紫月,叶凡"));
        movies.add(new Movie("牧神记", 9.3, "秦牧"));
        movies.add(new Movie("凡人修仙传", 9.4, "韩立"));
        movies.add(new Movie("凡人修仙传", 9.4, "韩立"));

        //集合中如果存储对象, 该对象的类可以实现Comparable接口, 重写compareTo方法,指定排序规则
        // Sorted方法就可以按照规则进行排序, 否则报错
        movies.stream().sorted().forEach(System.out::println);

        System.out.println("------------------------------------------");
        //方式二: 利sorted的重载方法,指定比较规则
        movies.stream().sorted(new Comparator<Movie>() {
            @Override
            public int compare(Movie o1, Movie o2) {
                return Double.compare(o1.getScore(), o2.getScore());//这个逻辑可以封装到CompareTo中,实现特定方法引用
            }
        }).forEach(System.out::println);
        movies.stream().sorted(((o1, o2) -> Double.compare(o1.getScore(),o2.getScore())));
        //特定方法引用--->真的是越来越简洁了
        movies.stream().sorted(Movie::compareTo).forEach(System.out::println);

        System.out.println("------------------------------------------");
        //3、limit取前几个
        //每次都是返回一个新的Stream流对象
        //去新流的前三个
        movies.stream().sorted(Movie::compareTo).limit(3).forEach(System.out::println);

        movies.stream().sorted(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore()))).limit(3).forEach(System.out::println);
        System.out.println("-----------------------------------------");
        //4、跳过前几个skip
        movies.stream().sorted(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore()))).skip(3).forEach(System.out::println);

        //5、distinct 去重复
        // 去重复: 需要重写对象类的hashCode和equals方法
        System.out.println("-----------------------------------");
        //跟hashSet去重机制是一样的
        movies.stream().sorted(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore()))).distinct().forEach(System.out::println);

        //6、map加工方法: 把流的数据加工成新数据
        System.out.println("------------------------------");
        //加工, 就像,流水线上有很多水瓶,拿到这些水瓶,加个盖子,然后再放上去
        //底层肯定是遍历每个电影对象,给map加工,然后返回给别人继续存
        //map:映射                    加工成了字符串
        movies.stream().map(m -> m.getName() + "--->" + m.getScore()).forEach(System.out::println);

        //7、合并流
        //把两个流接起来
        Stream<String> s1 = Stream.of("张三", "楚留香", " 西门吹雪");
        Stream<String> s2 = Stream.of("李四", "陈平安");
        //public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
        //开发中合并的流是一样,就会统一, 不一样,就会使用Object进行接收
        //上面的泛型的意思: 返回的T必须是合并的父类,或者合并本身类型(这个必须是两个合并类的类型是一样是才行)
        Stream<String> concat = Stream.concat(s1, s2);


    }
}
